package org.utils.plugins;

import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * Created on 30 mai 2003
 * 
 * @author Manuel EVENO
 */
public class MutableURLClassLoader extends URLClassLoader
{
	/* The context to be used when loading classes and resources */
	protected AccessControlContext acc = null;
	/**
	 * @param urls
	 * @param parent
	 */
	public MutableURLClassLoader(URL[] urls, ClassLoader parent)
	{
		super(urls, parent);
	}
	/**
	 * @param urls
	 */
	public MutableURLClassLoader(URL[] urls)
	{
		super(urls);
	}
	/**
	 * @param urls
	 * @param parent
	 * @param factory
	 */
	public MutableURLClassLoader(
		URL[] urls,
		ClassLoader parent,
		URLStreamHandlerFactory factory)
	{
		super(urls, parent, factory);
	}
	/**
	 * @see java.net.URLClassLoader#addURL(java.net.URL)
	 */
	public void addURL(URL url)
	{
		super.addURL(url);
	}
	/**
	 * Creates a new instance of URLClassLoader for the specified
	 * URLs and parent class loader. If a security manager is
	 * installed, the <code>loadClass</code> method of the URLClassLoader
	 * returned by this method will invoke the
	 * <code>SecurityManager.checkPackageAccess</code> method before
	 * loading the class.
	 *
	 * @param urls the URLs to search for classes and resources
	 * @param parent the parent class loader for delegation
	 * @return the resulting class loader
	 */
	public static MutableURLClassLoader newMutableInstance(final URL[] urls,
						 final ClassLoader parent)
	{
		// Save the caller's context
		AccessControlContext acc = AccessController.getContext();
		// Need a privileged block to create the class loader
		MutableURLClassLoader ucl =
		(MutableURLClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return new FactoryMutableURLClassLoader(urls, parent);
			}
		});
		// Now set the context on the loader using the one we saved,
		// not the one inside the privileged block...
		ucl.acc = acc;
		return ucl;
	}
	/**
	 * Creates a new instance of URLClassLoader for the specified
	 * URLs and default parent class loader. If a security manager is
	 * installed, the <code>loadClass</code> method of the URLClassLoader
	 * returned by this method will invoke the
	 * <code>SecurityManager.checkPackageAccess</code> before
	 * loading the class.
	 *
	 * @param urls the URLs to search for classes and resources
	 * @return the resulting class loader
	 */
	public static MutableURLClassLoader newMutableInstance(final URL[] urls)
	{
		// Save the caller's context
		AccessControlContext acc = AccessController.getContext();
		// Need a privileged block to create the class loader
		MutableURLClassLoader ucl = (MutableURLClassLoader)
		AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return new FactoryMutableURLClassLoader(urls);
			}
		});
		// Now set the context on the loader using the one we saved,
		// not the one inside the privileged block...
		ucl.acc = acc;
		return ucl;
	}
	/**
	 * Creates a new instance of URLClassLoader for the specified
	 * URLs and default parent class loader. If a security manager is
	 * installed, the <code>loadClass</code> method of the URLClassLoader
	 * returned by this method will invoke the
	 * <code>SecurityManager.checkPackageAccess</code> before
	 * loading the class.
	 *
	 * @param urls the URLs to search for classes and resources
	 * @return the resulting class loader
	 */
	public static MutableURLClassLoader newMutableInstance()
	{
		return newMutableInstance(new URL[0]);
	}
}
/**
 * Internal URLClassLoader
 * Created on 30 mai 2003
 * 
 * @author Manuel EVENO
 */
final class FactoryMutableURLClassLoader extends MutableURLClassLoader
{
	FactoryMutableURLClassLoader(URL[] urls, ClassLoader parent)
	{
		super(urls, parent);
	}
	/**
	 * 
	 * @param urls
	 */
	FactoryMutableURLClassLoader(URL[] urls)
	{
		super(urls);
	}
	/**
	 * 
	 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
	 */
	public final synchronized Class loadClass(String name, boolean resolve)
		throws ClassNotFoundException
	{
		// First check if we have permission to access the package. This
		// should go away once we've added support for exported packages.
		SecurityManager sm = System.getSecurityManager();
		if (sm != null)
		{
			int i = name.lastIndexOf('.');
			if (i != -1)
				sm.checkPackageAccess(name.substring(0, i));
		}
		return super.loadClass(name, resolve);
	}
}

